package tools;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ThumbnailHelper {
	
	private static final String THUMBNAIL_DIR = Environment.getExternalStorageDirectory() + "/.visualschedule/";
	
	private ThumbnailHelper() { }
	
	public static Bitmap getImageBitmapThumbnail(final String imagePath, final int maxWidth, final int maxHeight) {
	       Bitmap bitmap = null;
	       
	       if (imagePath == null) {
	           return null;
	       } else {            
	           File file = new File(imagePath);
	           
	           if (file.exists()) {                
	               try {
	                   bitmap = getThumbnailBitmap(imagePath, maxWidth, maxHeight);
	               } catch (FileNotFoundException e) {
	                   return null;
	               }
	           } else {
	               return null;
	           }           
	       }
	       
	       return bitmap;
	   }
	
	public static String getThumbnailPath(final String path, final int maxWidth, final int maxHeight) throws FileNotFoundException {
		if (!new File(path).exists()) {
			throw new FileNotFoundException();
		}
		
		//Get original file dimensions
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		
		BitmapFactory.decodeFile(path, options);
		final float orgWidth = options.outWidth;
		final float orgHeight = options.outHeight;
		final float ratioWidth = orgWidth / orgHeight;
		final float ratioHeight = orgHeight / orgWidth;
		
		
		//Calculate thumbnail width and height
		float thumbWidth = orgWidth;
		float thumbHeight = orgHeight;
		
		if (thumbWidth < maxWidth && thumbHeight < maxHeight) {
			if (thumbWidth > thumbHeight) {
				thumbWidth = maxWidth;
				thumbHeight = maxWidth * ratioHeight;
			} else {
				thumbHeight = maxHeight;
				thumbWidth = maxHeight * ratioWidth;
			}
		}
		
		while (thumbWidth > maxWidth || thumbHeight > maxHeight) {
			if (thumbHeight > maxHeight) {
				thumbHeight = maxHeight;
				thumbWidth = thumbHeight * ratioWidth;
			} 
			
			if (thumbWidth > maxWidth) {
				thumbWidth = maxWidth;
				thumbHeight = thumbWidth * ratioHeight;
			}			
		}
		
		
		
		//Load/Create thumbnail
		String result;
		final String thumbnailPath = thumbnailPath(path, (int)thumbWidth, (int)thumbHeight);
		if (new File(thumbnailPath).exists()) {
			//result = thumbnailPath;
			result = createThumbnail(path, (int)thumbWidth, (int)thumbHeight);
		} else {
			result = createThumbnail(path, (int)thumbWidth, (int)thumbHeight);	
		}
		
		return result;
	}
	
	public static Bitmap getThumbnailBitmap(final String path, final int maxWidth, final int maxHeigth) throws FileNotFoundException {
		return BitmapFactory.decodeFile(getThumbnailPath(path, maxWidth, maxHeigth));
	}
	
	private static String createThumbnail(final String filename, final int width, final int height) throws FileNotFoundException {
        //Valid file?
	    if (!new File(filename).exists()) {
	        throw new FileNotFoundException(filename + " does not exist");
	    }
            
        //Create thumbnail bitmap
        final Bitmap originalBitmap = BitmapFactory.decodeFile(filename);        
        final Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, width, height, true);
        
        try {
            final File thumbDir = new File(THUMBNAIL_DIR);
            if (!thumbDir.exists()) {
                thumbDir.mkdir();
            }
            
            //Create new output file. Truncate filename, width and height to get a unique thumbnail
            //filename for this specific thumbnail.
            final FileOutputStream out = new FileOutputStream(thumbnailPath(filename, width, height));
            scaledBitmap.compress(CompressFormat.JPEG, 95, out);
            out.flush();
            out.close();
            
        } catch (FileNotFoundException e) {
            Log.e("createThumbnail", e.getMessage());
        } catch (IOException e) {
            Log.e("createThumbnail", e.getMessage());
        }
        
        originalBitmap.recycle();
        scaledBitmap.recycle();
        
		return thumbnailPath(filename, width, height);
    }
	
	public static void removeThumbnail(final String path, final int width, final int height) {
		final File thumbnail = new File(thumbnailPath(path, width, height));
		
		if (thumbnail.exists()) {
			thumbnail.delete();
		}
	}
	
	public static void removeThumbnails(final String path) {
		// our filename filter (filename pattern matcher)
		class SearchFilter implements FilenameFilter {
			public boolean accept(final File dir, final String search) {
			    return search.startsWith(path);
			}
	    }
		
		final String[] files = new File(THUMBNAIL_DIR).list( new SearchFilter() );
		
		for (String file : files) {
			new File(file).delete();
		}
	}		
	
	
	public static void purgeThumbnails(final String path) {
		final File thumbnailFolder = new File(THUMBNAIL_DIR);
		deleteDirectory(thumbnailFolder);
	}
	
	private static boolean deleteDirectory(final File path) {
		if (path.exists()) {
			final File[] files = path.listFiles();
			for (int i=0; i<files.length; i++) {
				if (files[i].isDirectory()) {
					deleteDirectory(files[i]);
				} else {
					files[i].delete();
				}
			}
		}
		
		return path.delete();
	}

	private static String md5(final String input) {        
        MessageDigest message;
        String result = null;
        
		try {
			message = MessageDigest.getInstance("MD5");
			message.update(input.getBytes(),0,input.length());
			
	        result = new BigInteger(1, message.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			Log.e("md5", e.getMessage());
		}
		
		return result;
    }
	
    private static String thumbnailPath(final String originalFile, final int thumbnailWidth, final int thumbnailHeight) {    	
    	return THUMBNAIL_DIR + md5(originalFile) + "." + thumbnailHeight + "." + thumbnailWidth;
    }
}
